using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Design;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using OpenComposite.EII.Repository;

namespace OpenComposite.EII.RepositoryUIs
{
	[ToolboxItem(true)]
	[ToolboxBitmap(typeof(TreeView))]
	public class BusinessObjectTreeView : TreeView
	{
		#region Initialization
		public BusinessObjectTreeView()
		{
			_visibledatatypes = null;

			InitializeComponent();

			this.PathSeparator = ".";
			this.ImageList = imgList;

			tsmiOpen.Click += new EventHandler(tsmiOpen_Click);
			tsmiExpand.Click += new EventHandler(tsmiExpand_Click);
			tsmiCollapse.Click += new EventHandler(tsmiCollapse_Click);
		}
		#endregion

		#region Public Members

		#region Constants
		public const string BusinessObjectImageKey = "bobject";
		public const string BusinessObjectListImageKey = "list_of_bobjects";
		private ContextMenuStrip contextMenuStrip1;
		private ToolStripMenuItem tsmiOpen;
		private ToolStripSeparator toolStripSeparator1;
		private ToolStripMenuItem tsmiCollapse;
		private ToolStripMenuItem tsmiExpand;
		public const string NounImageKey = "noun";
		#endregion

		#region Properties
		public string VisibleDataTypes
		{
			get { return _visibledatatypes; }
			set
			{
				if ( _visibledatatypes != value ) {
					_visibledatatypes = value;
					fillTree();
				}
			}
		}

		public BusinessObject BusinessObject
		{
			get { return _bobject; }
			set
			{
				if ( _bobject != value ) {
					_bobject = value;
					OnBusinessObjectChanged();
				}
			}
		}
		#endregion

		#region Methods
		#endregion

		#endregion

		#region Protected Members

		#region Methods
		protected virtual void OnBusinessObjectChanged()
		{
			fillTree();
		}
		#endregion

		#endregion

		#region Private Members

		#region Variables
		private BusinessObject _bobject;
		private ImageList imgList;
		private string _visibledatatypes;
		#endregion

		#region Methods
		private void fillTree()
		{
			try {
				this.BeginUpdate();
				this.Nodes.Clear();

				createBObjectTree(this.BusinessObject, null);

			} finally {
				this.EndUpdate();
			}
		}

		private bool alreadyDefined(string name, TreeNode current)
		{
			while ( current != null ) {
				if ( current.Text == name ) return true;
				current = current.Parent;
			}
			return false;
		}

		private void createBObjectTree(BusinessObject bobjCurrent, TreeNode tnCurrent)
		{
			if ( bobjCurrent == null ) return;
			if ( alreadyDefined(bobjCurrent.Name, tnCurrent) ) return;
			// Create TreeNode for the current BusinessObject
			TreeNode tnBO = new TreeNode(bobjCurrent.Name);
			tnBO.Tag = bobjCurrent;
			tnBO.ImageKey = BusinessObjectImageKey;
			tnBO.SelectedImageKey = BusinessObjectImageKey;
			if ( tnCurrent == null )
				this.Nodes.Add(tnBO);
			else
				tnCurrent.Nodes.Add(tnBO);

			// Create TreeNodes for the Fields of current BusinessObject
			foreach ( BusinessObjectField field in bobjCurrent.BusinessObjectFields ) {
				if ( field.IsReference ) {
					BusinessObject boChild = field.BusinessObject;
					// add referenced BusinessObject/List
					if ( boChild != null ) {
						if ( !field.IsList ) {
							createBObjectTree(boChild, tnBO);
						} else {
							TreeNode tnList = new TreeNode(field.Name);
							tnList.ImageKey = tnList.SelectedImageKey = BusinessObjectListImageKey;
							tnList.Tag = boChild;
							tnBO.Nodes.Add(tnList);
							createBObjectTree(boChild, tnList);
						}
					}
				} else {
					Noun noun = field.Noun;
					if ( noun != null &&
						 ( string.IsNullOrEmpty(_visibledatatypes) ||
						   _visibledatatypes.ToLower().Contains(noun.DataType.ToLower()) ) ) {
						TreeNode tnField = new TreeNode(noun.Name);
						tnField.ImageKey = tnField.SelectedImageKey = NounImageKey;
						tnField.Tag = noun;
						tnBO.Nodes.Add(tnField);
					}
				}
			}
			if ( tnCurrent == null )
				tnBO.Expand();
		}
		#endregion

		#endregion

		#region Generated Code

		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BusinessObjectTreeView));
			this.imgList = new System.Windows.Forms.ImageList(this.components);
			this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
			this.tsmiOpen = new System.Windows.Forms.ToolStripMenuItem();
			this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
			this.tsmiCollapse = new System.Windows.Forms.ToolStripMenuItem();
			this.tsmiExpand = new System.Windows.Forms.ToolStripMenuItem();
			this.contextMenuStrip1.SuspendLayout();
			this.SuspendLayout();
			// 
			// imgList
			// 
			this.imgList.ImageStream = ( (System.Windows.Forms.ImageListStreamer)( resources.GetObject("imgList.ImageStream") ) );
			this.imgList.TransparentColor = System.Drawing.Color.Fuchsia;
			this.imgList.Images.SetKeyName(0, "bobject");
			this.imgList.Images.SetKeyName(1, "noun");
			this.imgList.Images.SetKeyName(2, "list_of_bobjects");
			// 
			// contextMenuStrip1
			// 
			this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.tsmiOpen,
            this.toolStripSeparator1,
            this.tsmiCollapse,
            this.tsmiExpand});
			this.contextMenuStrip1.Name = "contextMenuStrip1";
			this.contextMenuStrip1.Size = new System.Drawing.Size(137, 76);
			// 
			// tsmiOpen
			// 
			this.tsmiOpen.Name = "tsmiOpen";
			this.tsmiOpen.Size = new System.Drawing.Size(136, 22);
			this.tsmiOpen.Text = "Open";
			// 
			// toolStripSeparator1
			// 
			this.toolStripSeparator1.Name = "toolStripSeparator1";
			this.toolStripSeparator1.Size = new System.Drawing.Size(133, 6);
			// 
			// tsmiCollapse
			// 
			this.tsmiCollapse.Image = global::OpenComposite.Repository.Properties.Resources.tree_collapseall;
			this.tsmiCollapse.Name = "tsmiCollapse";
			this.tsmiCollapse.Size = new System.Drawing.Size(136, 22);
			this.tsmiCollapse.Text = "Collapse All";
			// 
			// tsmiExpand
			// 
			this.tsmiExpand.Image = global::OpenComposite.Repository.Properties.Resources.tree_expandall;
			this.tsmiExpand.Name = "tsmiExpand";
			this.tsmiExpand.Size = new System.Drawing.Size(136, 22);
			this.tsmiExpand.Text = "Expand All";
			// 
			// BusinessObjectTreeView
			// 
			this.LineColor = System.Drawing.Color.Black;
			this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.BusinessObjectTreeView_MouseClick);
			this.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.BusinessObjectTreeView_AfterSelect);
			this.contextMenuStrip1.ResumeLayout(false);
			this.ResumeLayout(false);

		}

		private System.ComponentModel.IContainer components;

		#endregion

		private void BusinessObjectTreeView_AfterSelect(object sender, TreeViewEventArgs e)
		{
		}

		void tsmiCollapse_Click(object sender, EventArgs e)
		{
			this.CollapseAll();
		}

		void tsmiExpand_Click(object sender, EventArgs e)
		{
			this.ExpandAll();
		}

		void tsmiOpen_Click(object sender, EventArgs e)
		{
			IServiceProvider provider = this.GetService(typeof(IServiceProvider)) as IServiceProvider;
			IRepositoryItem item = SelectedNode.Tag as IRepositoryItem;
			if ( item == null ) return;
			Helpers.ShowDetails(item, provider);
		}

		private void BusinessObjectTreeView_MouseClick(object sender, MouseEventArgs e)
		{
			this.SelectedNode = this.GetNodeAt(e.Location);
			if ( e.Button == MouseButtons.Right ) {
				contextMenuStrip1.Show(this, e.Location);
			}
		}
	}
}
